/*
 * @(#)AutoGeneratorEx.java 1.0 2020年06月04日
 *
 *  Copyright (c) 2016, YUNXI. All rights reserved.
 *  YUNXI PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.baomidou.mybatisplus.generator;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import lombok.*;
import lombok.experimental.Accessors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Map;

/**
 * <p>Title:AutoGeneratorEx</p>
 * <p>Description: </p>
 *
 * @author 子曰
 * @date 2020/6/4 12:46
 * @since 0.1.0
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper=false)
public class AutoGeneratorEx extends AutoGenerator {

    private static final Logger logger = LoggerFactory.getLogger(AutoGeneratorEx.class);

    /**
     * 配置信息
     */
    protected ConfigBuilder config;
    /**
     * 注入配置
     */
    @Getter(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    protected InjectionConfig injectionConfig;
    /**
     * 数据源配置
     */
    private DataSourceConfig dataSource;
    /**
     * 数据库表配置
     */
    private StrategyConfig strategy;
    /**
     * 包 相关配置
     */
    private PackageConfig packageInfo;
    /**
     * 模板 相关配置
     */
    private TemplateConfig template;
    /**
     * 全局 相关配置
     */
    private GlobalConfig globalConfig;
    /**
     * 模板引擎
     */
    private AbstractTemplateEngine templateEngine;

    /**
     * 生成代码
     */
    @Override
    public void execute() {
        logger.debug("==========================准备生成文件...==========================");
        // 初始化配置
        if (null == config) {
            config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig);
            //清除原来模板，添加自定义部分
            config.getPathInfo().clear();
            //requestdto
            config.getPackageInfo().put(ConstValEx.REQUEST_DTO, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getRequestDto()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getRequestdto(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getIApi() + "/src/main/java", ConstValEx.REQUEST_DTO_PATH, ConstValEx.REQUEST_DTO, config.getPackageInfo());
            //responsedto
            config.getPackageInfo().put(ConstValEx.RESPONSE_DTO, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getResponseDto()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getResponsedto(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getIApi() + "/src/main/java", ConstValEx.RESPONSE_DTO_PATH, ConstValEx.RESPONSE_DTO, config.getPackageInfo());
            //api
            config.getPackageInfo().put(ConstValEx.IAPI, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getIApi()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getIapi(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getIApi() + "/src/main/java", ConstValEx.IAPI_PATH, ConstValEx.IAPI, config.getPackageInfo());
            //iquerapi
            config.getPackageInfo().put(ConstValEx.IQUERYAPI, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getIQueryApi()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getIqueryapi(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getIApi() + "/src/main/java", ConstValEx.IQUERYAPI_PATH, ConstValEx.IQUERYAPI, config.getPackageInfo());
            //eo
            config.getPackageInfo().put(ConstValEx.EO, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getEo()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getEo(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getDao() + "/src/main/java", ConstValEx.EO_PATH, ConstValEx.EO, config.getPackageInfo());
            //mapper
            config.getPackageInfo().put(ConstValEx.MPR, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getMpr()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getMpr(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getDao() + "/src/main/java", ConstValEx.MPR_PATH, ConstValEx.MPR, config.getPackageInfo());
            //das
            config.getPackageInfo().put(ConstValEx.DAS, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getDas()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getDas(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getDao() + "/src/main/java", ConstValEx.DAS_PATH, ConstValEx.DAS, config.getPackageInfo());
            //iservice
            config.getPackageInfo().put(ConstValEx.ISERVICE, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getIService()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getIservice(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getBiz() + "/src/main/java", ConstValEx.ISERVICE_PATH, ConstValEx.ISERVICE, config.getPackageInfo());
            //service
            config.getPackageInfo().put(ConstValEx.SVC, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getSvc()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getSvc(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getBiz() + "/src/main/java", ConstValEx.SVC_PATH, ConstValEx.SVC, config.getPackageInfo());
            //api
            config.getPackageInfo().put(ConstValEx.API, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getApi()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getApi(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getBiz() + "/src/main/java", ConstValEx.API_PATH, ConstValEx.API, config.getPackageInfo());
            //queryapi
            config.getPackageInfo().put(ConstValEx.QUERYAPI, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getQueryApi()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getQueryapi(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getBiz() + "/src/main/java", ConstValEx.QUERYAPI_PATH, ConstValEx.QUERYAPI, config.getPackageInfo());
            //rest
            config.getPackageInfo().put(ConstValEx.REST, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getRest()));
            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getRest(), globalConfig.getOutputDir()
                + File.separator + globalConfig.getOutputDir().substring(globalConfig.getOutputDir().lastIndexOf(File.separator)+1)
                + ((PackageConfigEx)packageInfo).getSvr() + "/src/main/java", ConstValEx.REST_PATH, ConstValEx.REST, config.getPackageInfo());

//            config.getPackageInfo().put(ConstValEx.EO, joinPackage(packageInfo.getParent(), ((PackageConfigEx)packageInfo).getEo()));
//            setPathInfo(config.getPathInfo(), ((TemplateConfigEx)template).getEo(), globalConfig.getOutputDir(), ConstValEx.EO_PATH, ConstValEx.EO, config.getPackageInfo());
            if (null != injectionConfig) {
                injectionConfig.setConfig(config);
            }

        }
        if (null == templateEngine) {
            // 为了兼容之前逻辑，采用 Velocity 引擎 【 默认 】
            templateEngine = new VelocityTemplateEngine();
        }
        // 模板引擎初始化执行文件输出
        templateEngine.init(this.pretreatmentConfigBuilder(config)).mkdirs().batchOutput().open();
        logger.debug("==========================文件生成完成！！！==========================");
    }

    /**
     * 连接父子包名
     *
     * @param parent     父包名
     * @param subPackage 子包名
     * @return 连接后的包名
     */
    private String joinPackage(String parent, String subPackage) {
        if (StringUtils.isEmpty(parent)) {
            return subPackage;
        }
        return parent + StringPool.DOT + subPackage;
    }

    private void setPathInfo(Map<String, String> pathInfo, String template, String outputDir, String path, String module, Map<String, String> packageInfo) {
        if (StringUtils.isNotEmpty(template)) {
            pathInfo.put(path, joinPath(outputDir, packageInfo.get(module)));
        }
    }

    /**
     * 连接路径字符串
     *
     * @param parentDir   路径常量字符串
     * @param packageName 包名
     * @return 连接后的路径
     */
    private String joinPath(String parentDir, String packageName) {
        if (StringUtils.isEmpty(parentDir)) {
            parentDir = System.getProperty(ConstVal.JAVA_TMPDIR);
        }
        if (!StringUtils.endsWith(parentDir, File.separator)) {
            parentDir += File.separator;
        }
        packageName = packageName.replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
        return parentDir + packageName;
    }
}
